﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DreamOnGameEngine.Utils
{
    /// <summary>
    /// Custom Random number generator
    /// </summary>
    public class CRandom
    {
        private uint rseed;
        //private uint rseed_sp;
        private ulong[] mt;
        private int mti;
        /// <summary>
        /// Default Constructor
        /// </summary>
        public CRandom()
        {
            rseed=1;
           // rseed_sp=0;
            mti=624+1;
            mt = new ulong[624];
        }
        /// <summary>
        /// Gets a random Uit, up to number n
        /// </summary>
        /// <param name="n">Maximum number</param>
        /// <returns>Random number</returns>
        public uint Random(uint n)
        {
            
            ulong y;
            ulong[] mag01={0x0,0x9908b0df};
            if (n == 0)
                return 0;
            if (mti >= 624)
            {
                int kk;
                if (mti == 625)
                    RandomSeed=4357;
                for (kk = 0; kk < 624 - 397; kk++)
                {
                    y = (mt[kk] & 0x80000000) | (mt[kk + 1] & 0x7fffffff);
                    mt[kk] = mt[kk + 397] ^ (y >> 1) ^ mag01[y & 0x1];
                }
                for (; kk < 624 - 1; kk++)
                {
                    y = (mt[kk] & 0x80000000) | (mt[kk + 1] & 0x7fffffff);
                    mt[kk] = mt[kk + (397 - 624)] ^ (y >> 1) ^ mag01[y & 0x1];
                }
                y = (mt[624 - 1] & 0x80000000) | (mt[0] & 0x7fffffff);
                mt[624 - 1] = mt[397 - 1] ^ (y >> 1) ^ mag01[y & 0x1];
                mti = 0;
            }

            y = mt[mti++];
            y ^= (y >> 11);
            y ^= (y << 7) & 0x9d2c5680;
            y ^= (y << 15) & 0xefc60000;
            y ^= (y >> 18);

            return ((uint)y % n);
        }
        /// <summary>
        /// Returns a random float from 0.0 to 1.0
        /// </summary>
        /// <returns>Random floar</returns>
        public float Random()
        {
            int r = (int)Random(0xffffffff);
            float devisor = (float)0xffffffff;
            return (r / devisor) + 0.5f;
        }
        /// <summary>
        /// Random Seed
        /// </summary>
        public uint  RandomSeed
        {
            get { return rseed;}
            set
            {
                mt[0] = value & 0xffffffff;
                for (mti = 1; mti < 624; mti++)
                    mt[mti] = (69069 * mt[mti - 1]) & 0xffffffff;

                rseed = value;
            }
        }
        /// <summary>
        /// Sets the seed to the current UNIX TimeStamp
        /// </summary>
        public void Randomize()
        {
            RandomSeed = (uint)DateTime.Now.ConvertToTimestamp();
        } 
    }
}
